class TrieNode {
  constructor() {
      this.children = {};
      this.isEndOfWord = false;
      this.data = null;
  }
}

export class Trie {
  constructor() {
      this.root = new TrieNode();
      this.searchCache = {}; // 缓存搜索结果
  }

  // 批量插入数据
  batchInsert(dataList) {
      dataList.forEach(({ label, value }) => {
          this.insert(label, value);
      });
  }

  insert(word, data) {
      word = word.toLowerCase(); // 大小写不敏感
      let node = this.root;
      for (const char of word) {
          if (!node.children[char]) {
              node.children[char] = new TrieNode();
          }
          node = node.children[char];
      }
      node.isEndOfWord = true;
      node.data = data;
      this.searchCache = {}; // 插入新数据后清空缓存
  }

  // 更通用的模糊搜索方法
  fuzzySearch(keyword) {
      keyword = keyword.toLowerCase();
      if (this.searchCache[keyword]) {
          return this.searchCache[keyword];
      }
      const results = [];
      this._traverseTree(this.root, "", keyword, results);
      this.searchCache[keyword] = results;
      return results;
  }

  _traverseTree(node, currentWord, keyword, results) {
      if (node.isEndOfWord && currentWord.includes(keyword)) {
          results.push(node.data);
      }
      for (const char in node.children) {
          const newWord = currentWord + char;
          this._traverseTree(node.children[char], newWord, keyword, results);
      }
  }

  collectWords(node, results) {
      if (node.isEndOfWord) {
          results.push(node.data);
      }
      for (const child in node.children) {
          this.collectWords(node.children[child], results);
      }
  }

  // 压缩前缀树节点
  compress() {
      this._compressNode(this.root);
  }

  _compressNode(node) {
      while (Object.keys(node.children).length === 1) {
          const childKey = Object.keys(node.children)[0];
          const childNode = node.children[childKey];
          node.children = childNode.children;
          node.isEndOfWord = childNode.isEndOfWord;
          node.data = childNode.data;
      }
      for (const child in node.children) {
          this._compressNode(node.children[child]);
      }
  }
}